/// <reference path="../../index.d.ts" />
const Service = require("egg").Service
let gameConfig = require("../../config/game")
let {inviteReward} = gameConfig
let helper = require("../extend/helper")
let ObjBase = require("obj-base")
let debug = require("debug")("empire:service")
// debug.enabled = true
class EmpireService extends Service {
	constructor(ctx) {
		super(ctx)
		this.Game = this.app.model.Game
		this.AssistData = this.app.model.Game.AssistData
		this.GameUser = this.app.model.Game.GameUser
		this.GameUserSign = this.app.model.Game.GameUserSign
	}
	getReward(num) {
		let o = inviteReward.find(function (val, index, all) {
			if (!all[index + 1]) {
				return true
			}
			if (all[index].num <= num && all[index + 1].num > num) {
				return true
			}
			return false
		})
		return o
	}
	getAllReward() {
		let arr = new Array(100).fill(0).map((v, i) => i)
		return arr.map((v) => {
			let obj = this.getReward(v + 1)
			if (obj) {
				return {sycee: obj.reward}
			}
		}).filter(Boolean)
	}

	/**
	 * @param {number[]} ids 
	 */
	removeEmpireHelp(ids) {// 过期的助力
		return this.AssistData.destroy({
			where: {
				id: {
					$in: ids
				}
			}
		})// 删除过期的东西
	}

	/**
 		*  是否存在游戏玩家
 	 */
	async existUser(oid) {
		return await this.GameUser.count({
			where: {
				oid
			}
		})
	}
	async saveOidIfExist(oid, obj) {
		let ctx = this.ctx
		let redis = this.app.redis
		let userKey = ctx.app.config.redisPrefix.gameUser + oid
		let str = await redis.get(userKey)
		if (!str || !(obj instanceof Object))
			return
		else {
			let o = JSON.parse(str) // 原始数据
			if (!(o instanceof Object)) {
				return
			}
			for (const key in obj) {
				if (!Object.prototype.hasOwnProperty.call(o, key)) {
					return
				}
			}// 防扩展
			let res = Object.assign(o, obj)
			await redis.set(userKey, JSON.stringify(res))
		}
	}
	// 玩家数据/缓存
	async getGameUserCache(oid) {
		let ctx = this.ctx
		let GameUser = ctx.app.model.Game.GameUser
		let key = ctx.app.config.redisPrefix.gameUser + oid
		let redisData = await ctx.app.redis.get(key)
		if (!redisData)// 找不到缓存
			return undefined
		let gameUser = JSON.parse(redisData)
		gameUser.unlock_map = gameUser.unlock_map || 1
		// gameUser.last_login = Date.now()
		gameUser = GameUser.build(gameUser, {isNewRecord: false})
		if (gameUser._changed) {
			gameUser._changed.id = false
			gameUser._changed.oid = false
			gameUser._changed.create_at = false
			gameUser._changed.ip = false
		}
		if (gameUser.oid != oid) {
			ctx.app.logger.warn("缓存不一致")
		}
		if (gameUser.id && gameUser.oid && gameUser.level && gameUser.oid) {
			return gameUser
		}
		else
			return undefined
	}
	async getGameUser(oid) {
		let user = await this.getGameUserCache(oid)
		if (!user) {
			user = await this.GameUser.findOne({
				where: {
					oid
				}
			})
		}
		return user
	}
	/* 
	初始化数据
 	*/
	async findOrCreateUser(oid) {
		let ip
		try {
			var ipStr = this.ctx.get("X-Real-IP")
			ip = ipStr && helper.ipV4toInt(ipStr)
		} catch (error) {
			ip && this.ctx.logger.warn(`ip:${ipStr}`)
		}

		let res = (await this.GameUser.findOrCreate({
			where: {
				oid
			},
			defaults: {total_coin: 1, popularity: 0, sycee: 0, create_at: Date.now(), last_login: Date.now(), level: 1, sell_count: 1, oid, ip: ip || null, unlock_map: 1, },
		}))
		return res
	}
	/* 
	获取徒弟
	 */
	async getApprentice(oid) {
		return this.GameUser.findAll({
			where: {
				inviteid: oid
			},
			attributes: ["oid"],
			order: [["create_at", "desc"]]
		}).then(v => {
			return v.map(v => v.oid)
		})
	}

	// }
	/* 	async getSignRewardCache(oid) {
		let gameUser = this.ctx.gameUser
		if (!gameUser) {
			this.ctx.logger.error("gameUser")
			return
		}
		// /date: new Date().toLocaleDateString()
		let obj = this.app.redis.set("oid#sign#" + gameUser.oid)
		if (gameUser)
			this.app.redis.set("oid#sign#" + gameUser.oid, JSON.stringify(res), "ex", (helper.getToDay() + 1000 * 24 * 3600 - Date.now()) / 1000)
	} 
	*/
	async getHistorySignCache(oid) {
		// await this.app.redis.del("empire#getHistorySignCache#" + oid)
		let dataList = await this.service.db.getSet("empire#getHistorySignCache#" + oid, {
			noExist: async () => {
				let signList = (await this.GameUserSign.findAll({
					where: {
						oid,
						sign_time: {
							$lt: helper.getToDay() + 3600 * 24 * 1000
						}
					},
					limit: 8,
					order: [["sign_time", "desc"]] // id 降
				})).map(v => v.toJSON())
				//  查找
				let signListDat = signList
				//  排序
				let today = helper.getToDay()
				let effList = []
				for (let i = 0; i <= signList.length; i++) {
					let signStat = signList.find((v) => {
						if (v && v.sign_time) {
							return v.sign_time >= today - i * (1000 * 3600 * 24) && v.sign_time < today - (i - 1) * (1000 * 3600 * 24) && v.stat
						}
					})
					if (signStat) {
						effList.push(signStat)
						if (signStat.stat == 2) {//新的一轮
							break
						}
					}
					else if (i != 0) {
						break
					}
				}
				signListDat = effList
				//  兼容
				if (!signListDat.find((v) => {
					return v.stat == 2
				}) && effList.length >= 2) {
					// 7 天++ 且没有
					debug("兼容久数据")
					let allSignTime = await this.GameUserSign.count(
						{
							where: {
								oid,
								sign_time: {
									$lt: helper.getToDay() + 3600 * 24 * 1000
								}
							}
						}
					)
					let signTime = allSignTime % 7
					signList.sort((v, v1) => {
						return v.sign_time < v1.sign_time ? -1 : 1
					})
					let slicePoint
					if (signTime == 0) {
						slicePoint = signList.length - 7
					} else {
						slicePoint = (signList.length - signTime)
					}
					signListDat = signList.slice(slicePoint)
				}

				signListDat.sort((v, v1) => {
					return v.sign_time < v1.sign_time ? -1 : 1
				})
				return signListDat
			},
			expire: helper.todayRemaining()
		})
		return dataList.data
	}

	async getSignReward(oid) {
		let gameUser = this.ctx.gameUser
		if (!gameUser) {
			this.ctx.logger.error("gameUser#getSignReward")
			return
		}

		let minCoin = 1000
		let minPopularity = 20
		let baseCoin = Math.max(gameUser.max_total_coin, minCoin / 0.05) || minCoin / 0.05
		let basePopularity = Math.max(gameUser.max_popularity, minPopularity / 0.05) || minPopularity / 0.05

		let signList = await this.getHistorySignCache(oid)
		let today = helper.getToDay()
		// 最后几天的数据
		let signTime = 0

		// 有效数据
		signTime = signList.length
		let hasSign = signList.find((v) => {
			if (v && v.sign_time) {
				debug(new Date(v.sign_time))
				//  确认错误.修改
				return v.sign_time >= today && v.sign_time < today + 1000 * 3600 * 24 && v.stat
			}
		})

		// 成功签到数据
		this.ctx.logger.info(`${oid} 签到次数${signTime}`)
		// 获取历史奖励数据

		if (signTime == 0 || (!signList[0] || signList[0].stat == false)) {// 一定没有数据// 没领取数据可以更新
			signList[0] = signList[0] || {}
			signList[0].reward = {total_coin: baseCoin * 0.05}//保存

			if (!signList[0].id)
				await this.GameUserSign.findOrCreate({
					defaults: {
						oid, stat: false, reward: signList[0].reward
					},
					where: {
						oid, stat: false, sign_time: null
					}
					// id: signList[0] && signList[0].id,
				})// 奖励数据
			else {
				await this.GameUserSign.update({
					reward: signList[0].reward
				}, {
					where: {
						id: signList[0].id
					}
				})// 奖励数据
			}
		}
		signList[0].reward = signList[0].reward || {}
		signList[0].reward = ObjBase.objFetchKeys(signList[0].reward, ["total_coin"])

		if (signTime <= 1 || (!signList[1] || signList[1].stat == false)) {
			signList[1] = signList[1] || {}

		}
		if (!signList[1].reward || !signList[1].reward.popularity) {
			signList[1].reward = {popularity: basePopularity * 0.05}
		} else {
			signList[1].reward = ObjBase.objFetchKeys(signList[1].reward, ["popularity"])
		}
		// signList[1].reward.popularity
		signList[2] = {reward: {sycee: 5}}
		signList[3] = {reward: {total_coin: signList[0].reward.total_coin * 5 || baseCoin * 0.25}}
		signList[4] = {reward: {popularity: signList[1].reward.popularity * 2 || basePopularity * 0.1}}
		signList[5] = {reward: {sycee: 10}}
		signList[6] = {
			reward: {
				total_coin: signList[0].reward.total_coin * 20 || baseCoin,
				popularity: signList[1].reward.popularity * 10 || basePopularity * 0.5,
				sycee: 60
			}
		}
		if (signTime == 7 && !hasSign) {
			signTime = 0
		}
		let res = {signReward: signList.map(v => v.reward), signTime, hasSign, date: new Date().toLocaleDateString(), signList}
		return res
		// redis 优化 此接口可以不需要反复获取
	}

	async countAssist(oid) {
		let ucount = await this.getCount(oid)
		ucount.assistCount++
		await ucount.save()
	}

	async getCount(oid) {
		let ucount = await this.Game.GameUserCount.findOne({
			where: {
				oid
			}
		})
		if (!ucount) {
			let assistCount = await this.Game.AssistData.count({
				where: {
					oid,
					helpid: {
						$ne: -1
					}
				}
			})
			ucount = this.Game.GameUserCount.build({oid, assistCount})
			await ucount.save()
		}
		return ucount
	}
}
module.exports = EmpireService